package com.xteam.xnetworkdisk.sys.controller;

import cn.hutool.core.io.resource.InputStreamResource;
import com.aliyun.oss.ServiceException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xteam.xnetworkdisk.sys.dao.FileDao;
import com.xteam.xnetworkdisk.sys.entity.FileEntity;
import com.xteam.xnetworkdisk.utils.FileLocalUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import javax.servlet.AsyncContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

@RestController
@RequestMapping("xnetworkdisk")
public class XNetWorkDiskController {
    @Autowired
    private FileLocalUtils fileLocalUtils;

    @Autowired
    private FileDao fileDao;

    /**
     * 文件下载
     * @param fileName
     * @return
     */
    @GetMapping("/download/{fileName}")
    public void downloadFile(@PathVariable("fileName") String fileName, HttpServletRequest request, HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Origin","*");
        AsyncContext asyncContext = request.startAsync();
        asyncContext.setTimeout(90 * 60 * 1000); // 设置超时时间（单位：毫秒）

        asyncContext.start(() -> {
            try {
                // 获取文件的完整路径
                String fullPath = fileLocalUtils.getFullPath(fileName);
                String contentType = Files.probeContentType(Paths.get(fullPath));
                contentType = (contentType != null) ? contentType : "application/octet-stream";

                // 查询数据库中的文件实体
                QueryWrapper<FileEntity> wrapper = new QueryWrapper<>();
                wrapper.like("file_path", "%" + fileName);
                FileEntity fileEntity = fileDao.selectOne(wrapper);

                if (fileEntity == null) {
                    response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                    return;
                }

                String fileNameR = fileEntity.getFileName();
                String encodedFileName = URLEncoder.encode(fileNameR, StandardCharsets.UTF_8.toString())
                        .replace("+", "%20");

                // 设置响应头
                response.setContentType(contentType);
                response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFileName + "\"");

                // 使用流将文件内容写入响应
                try (InputStream inputStream = fileLocalUtils.getFilePreviewInputStream(fullPath);
                     OutputStream outputStream = response.getOutputStream()) {

                    byte[] buffer = new byte[1024];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                    outputStream.flush(); // 确保数据发送完毕
                }
            } catch (IOException e) {
                e.printStackTrace();
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            } finally {
                asyncContext.complete(); // 完成异步请求
            }
        });
    }

    /**
     * 文件预览
     * @param fileName
     * @return
     */
    @GetMapping("/preview/{fileName}")
    public ResponseEntity<StreamingResponseBody> previewFile(@PathVariable("fileName") String fileName,HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Origin","*");
        try {
            String fullPath = fileLocalUtils.getFullPath(fileName);
            InputStream inputStream = fileLocalUtils.getFilePreviewInputStream(fullPath);
            String contentType = Files.probeContentType(Paths.get(fullPath));
            System.out.println(contentType);
            contentType = contentType != null ? contentType : "application/octet-stream";
            System.out.println(contentType);

            // 如果文件类型是文本文件，添加字符编码
            if (contentType.startsWith("text")) {
                contentType += "; charset=UTF-8";
            }

            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_TYPE, contentType);
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + Paths.get(fullPath).getFileName() + "\"");

            StreamingResponseBody stream = outputStream -> {
                byte[] buffer = new byte[1024];
                int bytesRead;
                try {
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                } catch (IOException e) {
                    throw new IOException("Error writing to output stream", e);
                } finally {
                    try {
                        inputStream.close(); // 确保在流操作完成后关闭输入流
                    } catch (IOException e) {
                        throw new IOException("Error closing input stream", e);
                    }
                }
            };

            return new ResponseEntity<>(stream, headers, HttpStatus.OK);
        } catch (IOException e) {
            // 处理文件读取异常
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        } catch (Exception e) {
            // 处理其他异常
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

    /**
     * M3U8 文件预览
     * @param fileName
     * @return
     */
    @GetMapping("/previewVideo/{fileName}")
    public ResponseEntity<StreamingResponseBody> previewFileVideo(@PathVariable("fileName") String fileName, HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Origin", "*");
        try {
            // 获取文件的完整路径
            String fullPath = fileLocalUtils.getFullPathTS(fileName);
            System.out.println(fullPath);
            // 如果不是 m3u8 文件，可以返回错误
            if (!fileName.endsWith(".m3u8")) {
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
            }
            // 读取 m3u8 文件内容
            InputStream inputStream = fileLocalUtils.getFilePreviewInputStream(fullPath);
            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_TYPE, "application/vnd.apple.mpegurl");
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + Paths.get(fullPath).getFileName() + "\"");

            StreamingResponseBody stream = outputStream -> {
                byte[] buffer = new byte[1024];
                int bytesRead;
                try {
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                } catch (IOException e) {
                    throw new IOException("Error writing to output stream", e);
                } finally {
                    try {
                        inputStream.close(); // 确保在流操作完成后关闭输入流
                    } catch (IOException e) {
                        throw new IOException("Error closing input stream", e);
                    }
                }
            };

            return new ResponseEntity<>(stream, headers, HttpStatus.OK);
        } catch (Exception e) {
            // 处理其他异常
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

    /**
     * 视频文件预览
     * @param fileName
     * @param response
     * @return
     */
    @GetMapping("/previewSegment/{fileName}")
    public ResponseEntity<StreamingResponseBody> previewSegment(@PathVariable("fileName") String fileName, HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Origin", "*");
        try {
            // 获取文件的完整路径
            String fullPath = fileLocalUtils.getFullPathTS(fileName);
            // 如果不是 .ts 文件，可以返回错误
            if (!fileName.endsWith(".ts")) {
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
            }
            // 读取 TS 文件内容
            InputStream inputStream = fileLocalUtils.getFilePreviewInputStream(fullPath);
            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_TYPE, "video/MP2T");
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + Paths.get(fullPath).getFileName() + "\"");

            StreamingResponseBody stream = outputStream -> {
                byte[] buffer = new byte[1024];
                int bytesRead;
                try {
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                } catch (IOException e) {
                    throw new IOException("Error writing to output stream", e);
                } finally {
                    try {
                        inputStream.close(); // 确保在流操作完成后关闭输入流
                    } catch (IOException e) {
                        throw new IOException("Error closing input stream", e);
                    }
                }
            };

            return new ResponseEntity<>(stream, headers, HttpStatus.OK);
        } catch (Exception e) {
            // 处理其他异常
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }






}
